#include "StdAfx.h"
#include "stdio.h"
#include "xhPLCCtrl.h"
#include "stdlib.h"


#define DKQ_TEST_NOT_PLC

#ifdef DKQ_TEST
DDLogInfo g_xLogInfo;
#endif

//#define DKQ_PLC_TEST

xhPLCCtrl::xhPLCCtrl(void)
{
	m_hWnd = NULL;

	m_dwWaitTime  = 5000;

	m_funMsgCallBack = NULL;
	m_lContext       = 0;
	m_pContext       = NULL;

	memset(m_xPartCode,0,sizeof(m_xPartCode));
	memset(m_xRecvBuf,0,sizeof(m_xRecvBuf));
	m_wRecvCmdType = 0;
	m_nRecvBufSize = 0;

	m_nConnecStatus = 0;

	m_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);

#ifdef DKQ_TEST
	g_xLogInfo.CreateLogDir("PLCCtrl",0x1000);
#endif
}

xhPLCCtrl::~xhPLCCtrl(void)
{
	UnInitialize();

	MySafeCloseHandle(m_hEvent);
}

int xhPLCCtrl::Initialize()
{
	DD_AUTO_LOCK xLock(&m_Sect);

    PlugReg::SetPlugFlag("PlugRay\\rgplc.a");

	return 0;
}

int xhPLCCtrl::UnInitialize()
{
	//DD_AUTO_LOCK xLock(&m_Sect);

	UnInit();

	return 0;
}

int xhPLCCtrl::SetHwnd(HWND hWnd)
{
	return 0;
}
//
int xhPLCCtrl::RegMsgCallBack(void *pfun, DWORD dwContext, void *pContext)
{
	m_funMsgCallBack = (PLCMsgCallBackFun)pfun;
	m_lContext          = dwContext;
	m_pContext          = pContext;

	return 0;
}


int xhPLCCtrl::GetPlugList(zkPlugDescs **ppDescs)
{
	m_xPlugDescs.nPlugDescs = 1;
	sprintf( m_xPlugDescs.arPlugDescs[0],"RG-PLC" );

	*ppDescs = &m_xPlugDescs;
	
	return 0;
}

int xhPLCCtrl::SelectPlug(char *pDescName)
{
	return 0;
}

int xhPLCCtrl::OpParam(void *pVoid)
{
	if( NULL == pVoid )
	{
		return DD_ERR_PARAMETER;
	}
	int nRet = DD_ERR_SUCCESS;

	zkPlugParam *pPlugParam = (zkPlugParam*)pVoid;

	switch( pPlugParam->dwType )
	{
	case ePlug_Parma_GetRegisterInfo:
		{
			pPlugParam->bAutoDel = FALSE;
			pPlugParam->pParam   = (void*)&m_xRegParam;
		}
		break;
	case ePlug_Parma_SetRegisterInfo:
		{
			zkPlugRegParam *pReg = (zkPlugRegParam *)pPlugParam->pParam;
			if( NULL != pReg && sizeof(zkPlugRegParam) == pPlugParam->nParamSize )
			{
				PlugReg::SetRegisterCode( pReg->szRegisterCode );
			}
		}
		break;
	default:
		break;
	}

	return 0;
}



int xhPLCCtrl::UnInit()
{
	DDThread::DDThdUnInit();
	m_xCom.Close();

	return 0;
}

int xhPLCCtrl::SetComCfg(zkComCfg *pCfg)
{
	DD_AUTO_LOCK xLock(&m_Sect);

	UnInit();

	do 
	{
#ifdef DKQ_TEST_PLC
		g_xLogInfo.WriteLog(__FILE__,__LINE__,"SetComCfg:nCom %d,nBaudRate %d,nCheck %d,nStopBit %d,nDataBit %d",pCfg->nCOM,pCfg->nBaudRate,pCfg->nCheck,pCfg->nStopBit,pCfg->nDataBit);
#endif
		BOOL bRet = m_xCom.Open(pCfg->nCOM,pCfg->nBaudRate,pCfg->nCheck,pCfg->nStopBit,pCfg->nDataBit); 
		if( !bRet )
		{
			break;
		}

		m_dwWaitTime = pCfg->nTimeout;
		if( m_dwWaitTime < 1000 )
		{
			m_dwWaitTime = 1000;
		}

		if( !DDThread::DDThdInit() )
		{
			break;
		}

#ifdef DKQ_TEST_PLC
		g_xLogInfo.WriteLog(__FILE__,__LINE__,"SetComCfg:success");
#endif

		return 0;

	} while (false);

	UnInit();

	return -1;
}


int xhPLCCtrl::CheckConnect(int &nStatus)
{
	if( DDThread::m_bThreadRun )
	{
		nStatus = m_nConnecStatus;
	}
	else
	{
		nStatus = 0;
	}

	return 0;
}

int xhPLCCtrl::DDThdDispatch(HANDLE hExitEvent)
{
	BYTE xRecvBuf[COM_MAX_BUF_SIZE]={0};
	int  nRecvLen = 0;
	WORD wCmdType = 0;

	int nTimes = 200;

	m_nConnecStatus = 0;

	while( DDThread::m_bThreadRun )
	{
        if( nTimes-- < 0 )
		{
			m_nConnecStatus = 0;
		}
		nRecvLen = m_xCom.ReadData(xRecvBuf,COM_MAX_BUF_SIZE);
		if( CheckCRC(xRecvBuf,nRecvLen) )
		{
			nTimes = 200;
			m_nConnecStatus = 1;

			wCmdType = GetCommandType( (char*)xRecvBuf,nRecvLen );
			RecvCommand(wCmdType,xRecvBuf,nRecvLen);
		}
	}

	return 0;
}

#define RG_PLC_CMD_LEN 23
inline BOOL xhPLCCtrl::CheckCRC( BYTE *pBuffer,int nLength )
{
	if( nLength < RG_PLC_CMD_LEN )
	{
		return FALSE;
	}

	BYTE cCRC = 0;
	for(int i=0;i<RG_PLC_CMD_LEN-1;i++)
	{
		cCRC += pBuffer[i];
	}
	if( pBuffer[ RG_PLC_CMD_LEN-1 ] !=cCRC )
	{
		return FALSE;
	}

	return TRUE;
}

inline WORD xhPLCCtrl::GetCommandType(char *pCommand,int nLen)
{
	WORD wType = 0;
	int  nPos  = 0;
	if( nLen > 3 )
	{
		wType = sGetWord( (BYTE*)pCommand,nPos );
	}

	return wType;
}


inline int xhPLCCtrl::RecvCommand(WORD wCmdType,BYTE *pBuffer,int nBufLen)
{
	if( wCmdType < 0x2000 ) //hub
	{
		if( wCmdType >= 0x1300)// recv
		{
			DD_AUTO_LOCK xLock(&m_Sect);

			int nRet = RecvHubCmd(wCmdType,pBuffer,nBufLen);
			//
			int  nSendSize     = 0;
			BYTE szSendBuf[30] = {0};

			WORD wAckType = wCmdType + 1;
			sSetWord( wAckType,szSendBuf,nSendSize );
			SetByte( (DD_ERR_SUCCESS==nRet)?1:0,(BYTE*)szSendBuf,nSendSize );
			SetByte( 0x0D,(BYTE*)szSendBuf,nSendSize );
			SetCRC( szSendBuf,nSendSize );

			m_xCom.WriteData( szSendBuf,nSendSize );
		}
		else
		{
			if( m_wAskType + 1 == wCmdType )
			{
				m_wRecvCmdType = wCmdType;
				m_nRecvBufSize = nBufLen;
				memcpy(m_xRecvBuf,pBuffer,nBufLen);

				::SetEvent(m_hEvent);
			}
		}
	}
	else //image
	{
		if( wCmdType >= 0x2300)// recv
		{
			DD_AUTO_LOCK xLock(&m_Sect);

			int nRet = RecvImgCmd(wCmdType,pBuffer,nBufLen);
			//
			int  nSendSize     = 0;
			BYTE szSendBuf[30] = {0};

			WORD wAckType = wCmdType + 1;
			sSetWord( wAckType,szSendBuf,nSendSize );
			SetWord( (DD_ERR_SUCCESS==nRet)?1:0,(BYTE*)szSendBuf,nSendSize );
			SetCRC( szSendBuf,nSendSize );

			m_xCom.WriteData( szSendBuf,nSendSize );
		}
		else
		{
			if( m_wAskType + 1 == wCmdType )
			{
				m_wRecvCmdType = wCmdType;
				m_nRecvBufSize = nBufLen;
				memcpy(m_xRecvBuf,pBuffer,nBufLen);

				::SetEvent(m_hEvent);
			}
		}
	}
	

	return 0;
}

inline int xhPLCCtrl::RecvHubCmd(WORD wCmdType,BYTE *pBuffer,int nBufLen)
{
	int nRet = -1;
	int nPos = 2;
	switch( wCmdType )
	{
	case PLCHub_Recv_HubSize:
		{
			zkHubRecvSize val;
			val.fA      = (float)sGetDword( pBuffer,nPos);
			val.fHeight = (float)sGetDword( pBuffer,nPos);

			val.fA      *= 0.01f;
			val.fHeight *= 0.01f;
			//test///
			val.fHeight = 300.0f;
			nRet = m_funMsgCallBack(wCmdType,(void*)&val,sizeof(zkHubRecvSize),m_lContext,m_pContext);
		}
		break;
	case PLCHub_Recv_HubInfo:
		{
			zkHubRecvInfo val;
			strcpy(val.szUnitType,(char*)pBuffer[nPos]); nPos += 20;
			strcpy(val.szMakeNum, (char*)pBuffer[nPos]); nPos += 20;
			strcpy(val.szProdNum, (char*)pBuffer[nPos]); nPos += 20;
			nRet = m_funMsgCallBack(wCmdType,(void*)&val,sizeof(zkHubRecvInfo),m_lContext,m_pContext);
		}
		break;
	case PLCHub_Recv_BeginCapture:
		{
			nRet = m_funMsgCallBack(wCmdType,NULL,0,m_lContext,m_pContext);
		}
		break;
	case PLCHub_Recv_CheckBroken:
		{
			nRet = m_funMsgCallBack(wCmdType,NULL,0,m_lContext,m_pContext);
		}
 		break;
	case PLCHub_Recv_ArtConclusion:
		{
			int val = GetByte( pBuffer,nPos );

			nRet = m_funMsgCallBack(wCmdType,(void*)&val,sizeof(int),m_lContext,m_pContext);
		}
		break;
	}
	return nRet;
}

inline int xhPLCCtrl::RecvImgCmd(WORD wCmdType,BYTE *pBuffer,int nBufLen)
{
	int nRet = -1;
	int nPos = 2;
	switch( wCmdType )
	{
	case PLCImg_Recv_WorkNumber:
		{
			char sWorkNumber[40] = {0};
			char sWorkFlag[22]   = {0};

			//strcpy(sWorkNumber,(char*)pBuffer[nPos]); nPos += 20;
			memcpy(sWorkNumber,pBuffer+nPos,20); nPos += 20;

			nRet = m_funMsgCallBack(wCmdType,sWorkNumber,strlen(sWorkNumber),m_lContext,m_pContext);
			{	
				sWorkFlag[0] = sWorkNumber[7];
				sWorkFlag[1] = sWorkNumber[8];
				sWorkFlag[2] = '\0';
				m_funMsgCallBack(PLCImg_Recv_WorkFlag,(void*)sWorkFlag,strlen(sWorkFlag),m_lContext,m_pContext);
			}

#ifdef DKQ_TEST_PLC
			g_xLogInfo.WriteLog(__FILE__,__LINE__,"WorkNumber:%s,WorkFlag:%s",sWorkNumber,sWorkFlag);
#endif
		}
		break;
	case PLCImg_Recv_PointPos:
		{
			int val = GetWord( pBuffer,nPos );

			nRet = m_funMsgCallBack(wCmdType,(void*)&val,sizeof(int),m_lContext,m_pContext);

#ifdef DKQ_TEST_PLC
			g_xLogInfo.WriteLog(__FILE__,__LINE__,"PointPos:%d",val);
#endif
		}
		break;
	case PLCImg_Recv_WorkForm:
		{
			int val = GetWord( pBuffer,nPos );

			nRet = m_funMsgCallBack(wCmdType,(void*)&val,sizeof(int),m_lContext,m_pContext);
#ifdef DKQ_TEST_PLC
			g_xLogInfo.WriteLog(__FILE__,__LINE__,"WorkForm:%d",val);
#endif
		}
		break;
	case PLCImg_Recv_CheckBroken:
		{
			nRet = m_funMsgCallBack(wCmdType,NULL,0,m_lContext,m_pContext);
#ifdef DKQ_TEST_PLC
			g_xLogInfo.WriteLog(__FILE__,__LINE__,"CheckBroken");
#endif
		}
 		break;
	case PLCImg_Recv_ArtConclusion:
		{
			int val = GetWord( pBuffer,nPos );

			nRet = m_funMsgCallBack(wCmdType,(void*)&val,sizeof(int),m_lContext,m_pContext);
#ifdef DKQ_TEST_PLC
			g_xLogInfo.WriteLog(__FILE__,__LINE__,"ArtConclusion:%d",val);
#endif
		}
		break;
	}
	return nRet;
}


inline int xhPLCCtrl::GetCommandReturn(char *pCommand,int nLen)
{
	int nRet = 0;
	if( nLen > 4 )
	{
		nRet = *( (WORD*)(pCommand+2) );
	}

	if( 1 == nRet )
	{
		return DD_ERR_SUCCESS;
	}

	return DD_ERR_FAILURE;
}






inline int xhPLCCtrl::Ask(char *pSendBuffer,long lSendSize, LPVOID pOutBuf, DWORD dwOutBufSize ,LPDWORD dwBytesReturned)
{
#ifdef DKQ_TEST_NOT_PLC
	return 0;
#endif

	*dwBytesReturned = 0;

	DDERR_CODE	errCode = DD_ERR_FAILURE;

	ResetEvent(m_hEvent);
	m_wRecvCmdType = 0;

	if( m_xCom.WriteData(pSendBuffer,lSendSize) < 0 )
	{
		m_nConnecStatus = 0;
		return DD_ERR_COM_SEND;
	}

	DWORD dwWait = WaitForSingleObject(m_hEvent,m_dwWaitTime);
	if( WAIT_TIMEOUT == dwWait )
	{
		m_nConnecStatus = 0;

		errCode = DD_ERR_COM_TIMEOUT;
	}
	else if( WAIT_OBJECT_0 == dwWait )
	{
		m_nConnecStatus = 1;

		if( m_wAskType + 1 == m_wRecvCmdType )
		{
			errCode = (DDERR_CODE)GetCommandReturn((char*)m_xRecvBuf,m_nRecvBufSize);

			memcpy(pOutBuf,m_xRecvBuf,m_nRecvBufSize);
			*dwBytesReturned = m_nRecvBufSize;
		}
	}

#ifdef DKQ_TEST_PLC
	g_xLogInfo.WriteLog(__FILE__,__LINE__,"Ask: m_wAskType 0x%x,m_wRecvCmdType 0x%x,errCode %d,m_dwWaitTime %d",m_wAskType,m_wRecvCmdType,errCode,m_dwWaitTime);
#endif

	return errCode;
}


int xhPLCCtrl::SetConfig(DWORD dwCommand, void* pInBuf,  DWORD dwInBufSize)
{
#ifdef DKQ_PLC_TEST
    return 0;
#endif

	DD_AUTO_LOCK xLock(&m_Sect);

	BYTE  szSendBuffer[256] = {0};
	BYTE  szRecvBuffer[256] = {0};
	int   nSendSize = 0;
	DWORD dwRecvSize = 0;

	m_wAskType = (WORD)dwCommand;

	sSetWord( m_wAskType,(BYTE*)szSendBuffer,nSendSize );

	switch(dwCommand)
	{
//Hub///////////////////////////////////////
	case PLCHub_Set_Speed:
		{
			if( NULL == pInBuf || sizeof(zkHubSpeed) != dwInBufSize )
			{
				return DD_ERR_PARAMETER;
			}
			zkHubSpeed xSpeed = *( (zkHubSpeed*)pInBuf );
			xSpeed.fSpeed *= 100;

			SetByte(  (BYTE)xSpeed.nNumber,(BYTE*)szSendBuffer,nSendSize );
			sSetDword( (DWORD)xSpeed.fSpeed,(BYTE*)szSendBuffer,nSendSize );
		}
		break;
	case PLCHub_Set_CaptureFinished:
		{
		}
		break;
	case PLCHub_Set_AutoConclusion:
		{
			if( NULL == pInBuf || sizeof(int) != dwInBufSize )
			{
				return -1;
			}
			SetByte(  (BYTE)( *( (int*)pInBuf ) ),(BYTE*)szSendBuffer,nSendSize );
		}
		break;
//Image//////////////////////////////////////////
	case PLCImg_Set_CaptureFinished:
		{
			
#ifdef DKQ_TEST_PLC
			g_xLogInfo.WriteLog(__FILE__,__LINE__,"CaptureFinished");
#endif  
		}
		break;
	case PLCImg_Set_AutoConclusion:
		{
			if( NULL == pInBuf || sizeof(int) != dwInBufSize )
			{
				return -1;
			}
			SetWord(  (WORD)( *( (int*)pInBuf ) ),(BYTE*)szSendBuffer,nSendSize );
#ifdef DKQ_TEST_PLC
			g_xLogInfo.WriteLog(__FILE__,__LINE__,"AutoConclusion:%d",(WORD)( *( (int*)pInBuf ) ));
#endif
		}
		break;
	case PLCImg_Set_Template:
		{
			if( NULL == pInBuf || sizeof(int) != dwInBufSize )
			{
				return -1;
			}
			SetWord(  (WORD)( *( (int*)pInBuf ) ),(BYTE*)szSendBuffer,nSendSize );

#ifdef DKQ_TEST_PLC
			g_xLogInfo.WriteLog(__FILE__,__LINE__,"Template:%d",(WORD)( *( (int*)pInBuf ) ));
#endif
		}
		break;
	case PLCImg_Set_SavePointPos:
		{
			if( NULL == pInBuf || sizeof(int) != dwInBufSize )
			{
				return -1;
			}
			SetWord(  (WORD)( *( (int*)pInBuf ) ),(BYTE*)szSendBuffer,nSendSize );

#ifdef DKQ_TEST_PLC
			g_xLogInfo.WriteLog(__FILE__,__LINE__,"SavePointPos:%d",(WORD)( *( (int*)pInBuf ) ));
#endif
		}
		break;
	case PLCImg_Set_GotoPointPos:
		{
			if( NULL == pInBuf || sizeof(int) != dwInBufSize )  
			{
				return -1;
			}
			SetWord(  (WORD)( *( (int*)pInBuf ) ),(BYTE*)szSendBuffer,nSendSize );

#ifdef DKQ_TEST_PLC
			g_xLogInfo.WriteLog(__FILE__,__LINE__,"GotoPointPos:%d",(WORD)( *( (int*)pInBuf ) ));
#endif
		}
		break;
/////////////////////////////////////////////////
	default:
		{
			return -1;
		}
		break;
	}

	SetCRC( szSendBuffer,nSendSize );

	int nRet = Ask((char*)szSendBuffer,nSendSize,szRecvBuffer,256,&dwRecvSize); 
	if( DD_ERR_SUCCESS == nRet )
	{

	}
	return nRet;
}

inline int xhPLCCtrl::SetCRC( BYTE *pBuffer,int &nPos )
{
	BYTE cCRC = 0;
// 	for(int i=0;i<nPos;i++)
// 	{
// 		cCRC += pBuffer[i];
// 	}
// 	pBuffer[ nPos++ ] = cCRC;

	nPos = 22;
	for(int i=0;i<nPos;i++)
	{
		cCRC += pBuffer[i];
	}
	pBuffer[ nPos++ ] = cCRC;

	return 0;
}



int xhPLCCtrl::GetConfig(DWORD dwCommand, void* pOutBuf, DWORD dwOutBufSize,DWORD *pdwBytesReturned)
{

	return 0;
}



